// 这个分号的作用是防止和其他jquery插件合并时，别人不规范的jquery插件忘记使用分号结束
//影响到我们当前的插件，导致无法运行的问题。
;(function ($, window, document, undefined) {

    jsPlumb.importDefaults({
        // default drag options
        DragOptions: { cursor: 'pointer', zIndex: 2000 },
        // the overlays to decorate each connection with.  note that the label overlay uses a function to generate the label text; in this
        // case it returns the 'labelText' member that we set on each connection in the 'init' method below.
        ConnectionOverlays: [
            [ "Arrow", {//箭头？
                location: 1,
                visible:true,
                width:11,
                length:11,
                id:"ARROW",
                events:{
                    click:function() { console.log("you clicked on the arrow overlay")}
                }
            } ],
            [ "Label", {
                location: 0.5,
                id: "label",
                cssClass: "aLabel",
                events:{
                    tap:function() { console.log("you clicked on the label overlay"); }
                }
            }]
        ],
        EndpointStyle : { display:"none"},
        Container: "canvasPanel"
    });

    var connectorPaintStyle = {
        strokeWidth: 2,
        stroke: "#61B7CF",
        joinstyle: "round",
        outlineStroke: "white",
        outlineWidth: 2
    },
    //hover 连线样式
    connectorHoverStyle = {
        strokeWidth: 3,
        stroke: "#216477",
        outlineWidth: 5,
        outlineStroke: "white"
    };

    //基础端点
    var endpoint = {
        anchor:"Continuous",
        connector: [ "Flowchart", { stub: [1, 1], gap: 1, cornerRadius: 5, alwaysRespectStubs: true} ],
        connectorStyle: connectorPaintStyle,
        connectorHoverStyle: connectorHoverStyle,
        dragOptions: { },
        overlays: [
            [ "Label", {
                location: [0.5, 1.5],
                label: "Drag",
                cssClass: "endpointSourceLabel",
                visible:false
            } ]
        ]
    },
    //开始端点
    sourceEndpoint= $.extend({},{filter:".ep"},endpoint), 
    //结束端点
    targetEndpoint={
        dropOptions:{ hoverClass:"dragHover" },
        allowLoopback:true,
        anchor:"Continuous"
    };

    

    class BpmnFlowChart {
        constructor (el, options) {
          this.options = options;
          this.$el = $(el);
          this.$el_ = this.$el.clone();
		  this.$bPMNPlane = $("<bpmndi:BPMNPlane></bpmndi:BPMNPlane>")
		  this.$bPMNDiagram = $("<bpmndi:BPMNDiagram></bpmndi:BPMNDiagram>");
		  this.$process = $("<process></process>");
          this.$definitions = $("<definitions></definitions>")
                .attr("xmlns","http://www.omg.org/spec/BPMN/20100524/MODEL")
                .attr("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")
                .attr("xmlns:xsd","http://www.w3.org/2001/XMLSchema")
                .attr("xmlns:activiti","http://activiti.org/bpmn")
                .attr("xmlns:bpmndi","http://www.omg.org/spec/BPMN/20100524/DI")
                .attr("xmlns:omgdc","http://www.omg.org/spec/DD/20100524/DC")
                .attr("xmlns:omgdi","http://www.omg.org/spec/DD/20100524/DI")
                .attr("typeLanguage","http://www.w3.org/2001/XMLSchema")
                .attr("expressionLanguage","http://www.w3.org/1999/XPath")
                .attr("targetNamespace","http://www.activiti.org/ras");
          this.init();
        }

        init(){
            this.bindEvent();
			this.createBpmnDefinitions({
				"processKey":"MyProcess",
				"name":"流程名称",
				"desc":"流程描述"
			});
        }
		
		/**创建流程定义xml*/
		createBpmnDefinitions(params){
			if (!params.hasOwnProperty('processKey') || !params.hasOwnProperty('name')) {
                return;
            }
			let processKey = params.processKey,name=params.name,desc=params.desc?params.desc:"";
			this.$process.attr("id",processKey).attr("name",name).prepend("<documentation></documentation>");
			this.$process.children("documentation").text(desc);
			this.$bPMNPlane.attr("bpmnElement",processKey).attr("id","BPMNPlane_"+processKey);
			this.$bPMNDiagram.attr("id","BPMNDiagram_"+processKey).append(this.$bPMNPlane);
			this.$definitions.append(this.$process).append(this.$bPMNDiagram);
		}

        bindEvent(){
            //鼠标移入节点内事件，显示连线图标
            this.$el.on("mouseenter", ".node", function () {
                $(this).find(".ep").show();//显示连线点
                $(this).find(".delete").show();//显示删除图标
            });

            //鼠标移出节点内事件，隐藏连线图标
            this.$el.on("mouseleave", ".node", function () {
                //jsPlumb.selectEndpoints({source:$(this).attr("id")}).addClass("endpointHide");
                $(this).find(".ep").hide();//隐藏连线点
                $(this).find(".delete").hide();//隐藏删除图标
            });

            //删除节点
            this.$el.on("click", ".delete",function () {
                var $this = $(this);
                $.modal.confirm('确定要删除该节点吗',function(){
                    jsPlumb.removeAllEndpoints($this.parent().attr("id"));
                    $this.parent().remove();
                });
            });

            //节点点击选中效果
            this.$el.on("click", ".node", function () {
                $(this).addClass("node-select").siblings('.node').removeClass('node-select');
            });

            //双击修改任务名称
            this.$el.on("dblclick", "span", function () {
                var $this = $(this);
                layer.prompt({title: '任务名称', formType: 2, value: $this.text(),maxlength: 10}, function(text, index){
                    layer.close(index);
                    $this.text(text);
                  });
                return false;
            });

            this.dblclick();

            
        }

        dblclick(){

            //节点双击事件。点开配置详细信息
            this.$el.on("dblclick", ".node", e =>  {
                var $this = $(e.currentTarget);
                var $xml = this.$definitions;

                //console.log($xml.find("#"+$this.attr("id")).find("extensionElements").children()[0]);
                var $properties = $("<form></form>").addClass("form-horizontal");

                $xml.find("#"+$this.attr("id")).find("extensionElements").children().each(function(index, el) {
                    var $field = $(el);

                    var $line = $("<div></div>").addClass("form-group");

                    var $label = $("<label></label>").addClass("col-sm-4 control-label").text($field.attr("name"));

                    var $input = $("<div></div>").addClass("col-sm-5").append($("<input></input>").addClass("form-control"));

                    $line.append($label).append($input);

                    $properties.append($line);
                });

                var $container = $("<div class='container'></div");
                var $row = $("<div class='row'></div");
                $row.append($properties);
                $container.append($row);


                layer.open({
                    title: '任务详情',
                    type: 1,
                    maxmin: true,
                    skin: 'layui-layer-rim', //加上边框
                    area: ['500px', '300px'],
                    content: $container.html(),
                    anim: 4,
                    success: function(layero, index){
                       
                    },
                    end:function () {
                        
                    }
                });
            });
        }


        drawNode(params){
            if (!params.hasOwnProperty('left') || !params.hasOwnProperty('top')) {
                return;
            }
            if (!params.hasOwnProperty('node') && !params.hasOwnProperty('bpmnNode')) {
                return;
            }
            //画图
            let $node = params.hasOwnProperty('node')?params.node:this.bpmnNodeToNode(params.bpmnNode);
            $node.append($("<div class='ep'></div>")) //设置连线点
                 .append("<div class='delete'><i class='fa fa-close' style='color:#ed5565;'></i></div>")
                 .css("left", params.left+"px").css("top", params.top+"px").css("z-index",0).css("font-weight","bold");
            let name = $node.attr("name");
            //绑定jsplumb
            if(this.name==="startEvent"){
                this.$el.append($node);
                jsPlumb.makeSource($node,sourceEndpoint);
            }else if(this.name==="end"){
                this.$el.append($node);
                jsPlumb.makeTarget($node,targetEndpoint);
            }else {
                this.$el.append($node);
                jsPlumb.makeSource($node,sourceEndpoint);
                jsPlumb.makeTarget($node,targetEndpoint);
            }
            
			let $bPMNPlane = this.$bPMNPlane;
			let $definitions = this.$definitions;
            jsPlumb.draggable($node.attr("id"),{
                containment:this.$el,
                //grid: [10, 10], //网格
                filter:".ep",
                scroll:true,
                stop:function(){//位置改变
                    var left = parseInt($node.position().left);
                    var top = parseInt($node.position().top);
					$bPMNPlane.find("#BPMNShape_"+$node.attr("id")).children().attr("x",left).attr("y",top);
					console.log($definitions[0]);
                    //修改$definitions 中该节点的位置
                    //$bPMNShape.firstChild().attr("x",left).attr("y",top);
                }

            });

            //
            this.addNode($node);
            
        }

        /**连线*/
        drawFlow(params){
            var $flow = params.flow;
            jsPlumb.connect({
                        source: $flow.attr("sourceRef"),
                        target: $flow.attr("targetRef")
                    });
        }

        /**bpmn节点转html节点*/
        bpmnNodeToNode(bpmnNode){

            let id = bpmnNode.attr("id");

            var $thisNode;
            switch (bpmnNode.prop("tagName")) {
                case "startEvent":
                    $thisNode = this.options.start.clone();
                    break;
                case "endEvent":
                    $thisNode = this.options.end.clone();
                    break;
                case "serviceTask":
                     $thisNode = this.options.serviceTask.clone();
                     $thisNode.find('span').text(bpmnNode.attr("name"));
                    break;
                case "exclusiveGateway":
                     $thisNode = this.options.exclusivegateway.clone();
                    break;
                case "parallelGateway":
                     $thisNode = this.options.parallelgateway.clone();
                    break;
            }
            $thisNode.addClass("node").attr("id",id);
            return $thisNode;
        }

        /**html节点转bpmn流程节点*/
        nodeToBpmnNode(node){
            let type = node.attr("name");
            var $bpmnNode = $("<"+type+"></"+type+">").attr("id",node.attr("id"));
            switch(type){
                case "startEvent":
                    if(node.attr("timer")){
                        $bpmnNode.attr("name","开始事件");
                    }else {
                        $bpmnNode.attr("name","定时事件");
                    }
                    break;
                case "endEvent":
                    $bpmnNode.attr("name","结束事件");
                    break;
                /*
                case "parallelGateway":
                    $bpmnNode.attr("name","定时事件");
                    break;
                case "exclusiveGateway":
                    $bpmnNode.attr("name","定时事件");
                    break;
                */
                case "serviceTask":
                    $bpmnNode.attr("activiti:async","true").attr("activiti:exclusive","false").attr("name",node.find("span").text());
                    break;
                default:
                    break;
            }
            return $bpmnNode;

        }

		/*html节点转bpmn位置节点*/
		nodeToBPMNShape(node){
			let id = node.attr("id");
			var $bounds = $("<omgdc:Bounds></omgdc:Bounds>").attr("height",node.outerHeight(true)).attr("width",node.outerWidth(true)).attr("x",node.position().left).attr("y",node.position().top);
			var $bPMNShape = $("<bpmndi:BPMNShape></bpmndi:BPMNShape>").attr("bpmnElement",id).attr("id","BPMNShape_"+id).append($bounds);
			return $bPMNShape;
		}

        loadBpmnXml(params){
            if (!params.hasOwnProperty('xml')) {
                return;
            }

            let $definitions = params.xml;

			let $process = $definitions.find("process");

			this.createBpmnDefinitions({
				"processKey":$process.attr("id"),
				"name":$process.attr("name"),
				"desc":$process.children("documentation").text()
			});

            var $setting = $("<div></div>");

            var shapes = $definitions[0].getElementsByTagNameNS("http://www.omg.org/spec/BPMN/20100524/DI","BPMNShape");
            for(var i=0;i<shapes.length;i++){
                var shape = shapes[i];
                var bounds = shape.children[0];
                var position = {
                    id:$(shape).attr("bpmnElement"),
                    x:$(bounds).attr("x"),
                    y:$(bounds).attr("y")
                };

                $setting.data($(shape).attr("bpmnElement"),position);
            }

            var bpmnFlowChart = this;

           
            $definitions.find("process").find("serviceTask,startEvent,endEvent,parallelGateway,exclusiveGateway").each(function(index, ele){
                //debugger;
                var id = $(this).attr("id");
                var position = $setting.data(id);

                bpmnFlowChart.drawNode({
                    "top":position.y,
                    "left":position.x,
                    "bpmnNode":$(this)
                });
            });

            //画线sequenceFlow
            $definitions.find("sequenceFlow").each(function(index, ele){
                bpmnFlowChart.drawFlow({
                        "flow":$(this)
                    });
            });
        }

        /**xml操作方法*/

		addNode(node){//入参是html的节点对象
			var $bpmnNode = this.nodeToBpmnNode($(node));
			var $bPMNShape = this.nodeToBPMNShape($(node));
			this.$process.append($bpmnNode);
			this.$bPMNPlane.append($bPMNShape);
		}

        /**节点下添加field*/
        addField(){

        }

        /**添加连线的信息*/
        addBPMNEdge(){
			var $bPMNEdge = $("<bpmndi:BPMNEdge></bpmndi:BPMNEdge>");

			var $waypoint = $("omgdi:waypoint");
        }
    }

    const allowedMethods = [
        'drawNode',
        'drawFlow',
        'loadBpmnXml'
    ]

    BpmnFlowChart.DEFAULTS =  {//默认值
        //各种参数，各种属性
        idIndex : 100,                                  //id后缀序列
        canvasPanelId : "#canvasPanel",
        start : $("<div name='startEvent' class='node-border node-event'><i class='fa fa-play-circle-o fa-2x node-pic' style='color:#1ab394;'></i>开始</div>"),
        //定时
        timer : $("<div name='startEvent' timer='true' class='node-border node-event'><i class='fa fa-clock-o fa-2x node-pic' style='color:#1ab394;'> </i>定时</div>"),
        //任务
        serviceTask : $("<div name='serviceTask'  class='node-border node-task'><i class='iconfont icon-task node-pic' style='color:#1c84c6;'></i><span>任务</span></div>"),
        //并行网关
        parallelgateway : $("<div name='parallelGateway' ><i class='iconfont icon-parallelgateway  node-pic' style='font-size:38px;color:#23c6c8;'> </i></div>"),
        //互斥网关
        exclusivegateway : $("<div name='exclusiveGateway' ><i class='iconfont icon-exclusivegateway node-pic' style='font-size:38px;color:#f8ac59;'></i></div>"),
        //结束
        end: $("<div name='endEvent'  class='node-border node-event'><i class='fa fa-pause-circle-o fa-2x node-pic' style='color:#ed5565;'> </i>结束</div>"),
        nodes :[],
        bpmnNodes : []
    };


    $.BpmnFlowChart = BpmnFlowChart;
    $.BpmnFlowChart.DEFAULTS = BpmnFlowChart.DEFAULTS;
    $.fn.bpmnFlowChart = function (option, ...args) {
        let value;
        this.each((i, el) => {
          let data = $(el).data('bpmnFlowChart');
          const options = $.extend({}, BpmnFlowChart.DEFAULTS,typeof option === 'object' && option);
          if (typeof option === 'string') {
            if (!allowedMethods.includes(option)) {
              throw new Error(`Unknown method: ${option}`)
            }

            if (!data) {
              return
            }

            value = data[option](...args)
          }

          if (!data) {
            $(el).data('bpmnFlowChart', (data = new $.BpmnFlowChart(el, options)));
          }
        })

        return typeof value === 'undefined' ? this : value
    }



    $.fn.bpmnFlowChart.defaults = BpmnFlowChart.DEFAULTS;

    /**
     一、节点
     开始、定时、结束 、任务、并行网关、互斥网关

     二、
    */

})(jQuery, window, document);